﻿//#define TRACE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
using System.Windows.Media;

namespace Hockey.UILayer.Controls
{
    /// <summary>
    /// Text block adapting the font size accoring to the size of area
    /// </summary>
    internal class FontAdaptiveTextBlock: Control
    {
        public static readonly DependencyProperty ContentProperty;

        static FontAdaptiveTextBlock()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = string.Empty;
            metadata.BindsTwoWayByDefault = true;

            ContentProperty = DependencyProperty
                .Register("Content", typeof(string), typeof(FontAdaptiveTextBlock), metadata);            
        }

        /// <summary>
        /// Font margin
        /// </summary>
        private const double _fontFactor = 0.85d;

        /// <summary>
        /// Constructor
        /// </summary>
        public FontAdaptiveTextBlock()
        {
        }

        /// <summary>
        /// String to be drawn
        /// </summary>
        public string Content
        {
            get
            {
                return (string)GetValue(ContentProperty);
            }
            set
            {
                SetValue(ContentProperty, value);
            }
        }



        /// <summary>
        /// Overriding measuring of text in the Content property
        /// </summary>
        /// <param name="constraint"></param>
        /// <returns></returns>
        protected override Size MeasureOverride(Size constraint)
        {
            FontSize = CalculateFontSize(ref constraint) * _fontFactor;
            return constraint;
        }

        /// <summary>
        /// Rendering method
        /// </summary>
        protected override void OnRender(DrawingContext drawingContext)
        {
            if (Content == null)
                return;

            // create text
            Typeface typeFace = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch);
            FormattedText fText = new FormattedText(this.Content.ToString(), System.Threading.Thread.CurrentThread.CurrentUICulture, System.Windows.FlowDirection.LeftToRight,
                typeFace, this.FontSize, this.Foreground);

            // calculate the origin
            double x = (RenderSize.Width - fText.Width) / 2;
            double y = (RenderSize.Height - fText.Height) /2;

            // draw the text
            drawingContext.DrawText(fText, new Point(x, y));
        }
      
        /// <summary>
        /// Calculates the font size
        /// </summary>
        private double CalculateFontSize(ref Size renderSize)
        {
            if (this.Content == null)
                return FontSize;

            // set the font according to the height
            double fontHeight = renderSize.Height;
            fontHeight = 72d / 96d * fontHeight;

            // check the width of the text
            Typeface typeFace = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch);
            FormattedText fText = new FormattedText(this.Content.ToString(), System.Threading.Thread.CurrentThread.CurrentUICulture, System.Windows.FlowDirection.LeftToRight,
                typeFace, fontHeight, Brushes.Black);

            double width = fText.Width;
            double height = fText.Height;

            if (fText.Width > renderSize.Width)
            {
                double factor = renderSize.Width / fText.Width;
                fontHeight *= factor;
                width *= factor;
                height *= factor;
            }

            renderSize.Width = width;
            renderSize.Height = height;

            return fontHeight;
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property == ContentProperty)
            {
                InvalidateMeasure();
                InvalidateVisual();
            }

            base.OnPropertyChanged(e);
        }
    }
}
